#include "file_explorer.h"
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <unistd.h>
 #include <stdio.h>

static file_explorer_t *g_ptFileExplorer;

static void brower_file_event_handler(lv_event_t * e);
static void show_dir(char * path);
static void strip_ext(char *dir);
static bool is_end_with(const char * str1, const char * str2);


void file_explorer_ui_init(void) {

    g_ptFileExplorer = (file_explorer_t *)lv_mem_alloc(sizeof(file_explorer_t));

    lv_memset_00(g_ptFileExplorer->cur_path, sizeof(g_ptFileExplorer->cur_path));

    g_ptFileExplorer->cont = lv_obj_create(lv_scr_act());
    // lv_obj_set_width(g_ptFileExplorer->cont, LV_PCT(100));
    lv_obj_set_size(g_ptFileExplorer->cont, LV_PCT(100), LV_PCT(100));
    lv_obj_set_flex_grow(g_ptFileExplorer->cont, 1);

    g_ptFileExplorer->event_obj = lv_obj_create(g_ptFileExplorer->cont);
    lv_obj_set_size(g_ptFileExplorer->event_obj, LV_PCT(100), LV_PCT(100));

    /* 右侧文件浏览区域 */
    g_ptFileExplorer->brower_area = lv_obj_create(g_ptFileExplorer->cont);
    lv_obj_set_size(g_ptFileExplorer->brower_area, LV_PCT(100), LV_PCT(100));
    lv_obj_set_flex_flow(g_ptFileExplorer->brower_area, LV_FLEX_FLOW_COLUMN);

    // 展示在文件浏览列表之上的区域
    g_ptFileExplorer->head_area = lv_obj_create(g_ptFileExplorer->brower_area);
    lv_obj_set_size(g_ptFileExplorer->head_area, LV_PCT(100), LV_PCT(12));
    lv_obj_clear_flag(g_ptFileExplorer->head_area, LV_OBJ_FLAG_SCROLLABLE);

    // 展示当前路径
    g_ptFileExplorer->path_label = lv_label_create(g_ptFileExplorer->head_area);
    lv_label_set_text(g_ptFileExplorer->path_label, LV_SYMBOL_EYE_OPEN ".");
    lv_obj_center(g_ptFileExplorer->path_label);

    // 目录内容展示列表
    g_ptFileExplorer->file_table = lv_table_create(g_ptFileExplorer->brower_area);
    lv_obj_set_size(g_ptFileExplorer->file_table, LV_PCT(100), LV_PCT(84));
    lv_table_set_col_cnt(g_ptFileExplorer->file_table, FILE_TABLE_COLUMN_COUNT);
    for(int i=0; i<FILE_TABLE_COLUMN_COUNT; i++)
        lv_table_set_col_width(g_ptFileExplorer->file_table, i, 300);
    lv_obj_add_event_cb(g_ptFileExplorer->file_table, brower_file_event_handler, LV_EVENT_ALL, g_ptFileExplorer);
    // only scroll up and down
    lv_obj_set_scroll_dir(g_ptFileExplorer->file_table, LV_DIR_TOP | LV_DIR_BOTTOM);
}


void file_explorer_open_dir(char * path){
    show_dir(path);
}


void file_explorer_register_item_clicked_handler(lv_event_cb_t event_cb, void * user_data){
    lv_obj_add_event_cb(g_ptFileExplorer->event_obj, event_cb, LV_EVENT_VALUE_CHANGED, user_data);
}

char *file_explorer_get_cur_path(){
    return g_ptFileExplorer->cur_path;
}


char *file_explorer_get_cur_item(){
    return g_ptFileExplorer->cur_file;
}


static void brower_file_event_handler(lv_event_t * e)
{
    lv_event_code_t code = lv_event_get_code(e);

    if(code == LV_EVENT_VALUE_CHANGED) {
        //struct stat stat_buf;
        char file_name[FILE_EXPLORER_PATH_MAX_LEN];
        char * str_fn = NULL;
        uint16_t row;
        uint16_t col;

        memset(file_name, 0, sizeof(file_name));
        lv_table_get_selected_cell(g_ptFileExplorer->file_table, &row, &col);
        str_fn = lv_table_get_cell_value(g_ptFileExplorer->file_table, row, col);

        str_fn = str_fn+5;
        
        if((strcmp(str_fn, "..") == 0) && (strlen(g_ptFileExplorer->cur_path) > 3))
        {
            strip_ext(g_ptFileExplorer->cur_path);
            strip_ext(g_ptFileExplorer->cur_path); // 去掉最后的 '/' 路径
            lv_snprintf(file_name, sizeof(file_name), "%s", g_ptFileExplorer->cur_path);
        }
        else
        {
            if(strcmp(str_fn, "..") != 0){
                lv_snprintf(file_name, sizeof(file_name), "%s%s", g_ptFileExplorer->cur_path, str_fn);
            }
        }

        lv_fs_dir_t dir;
        if(lv_fs_dir_open(&dir, file_name) == LV_FS_RES_OK) {
            lv_fs_dir_close(&dir);
            show_dir(file_name);
        }
        else {
            if(strcmp(str_fn, "..") != 0) {
                g_ptFileExplorer->cur_file = str_fn;
                lv_event_send(g_ptFileExplorer->event_obj, LV_EVENT_VALUE_CHANGED, NULL);    // 将事件上报
            }
        }
    }
    else if(code == LV_EVENT_SIZE_CHANGED) {
        for(int i=0; i<FILE_TABLE_COLUMN_COUNT; i++)
            lv_table_set_col_width(g_ptFileExplorer->file_table, i, 300);    // 为什么无法使用比例 LV_PCT(28)

    }
}



static void show_dir(char * path)
{
    file_explorer_t * explorer = g_ptFileExplorer;

    char fn[FILE_EXPLORER_PATH_MAX_LEN];
    uint16_t iRow = 0;
    uint16_t iCol = 0;
    lv_fs_dir_t dir;
    lv_fs_res_t res;

    res = lv_fs_dir_open(&dir, path);
    if(res != LV_FS_RES_OK) {
        LV_LOG_USER("Open dir error %d!", res);
        return;
    }

    /* 上一级目录 */
    lv_table_set_cell_value_fmt(explorer->file_table, iRow, iCol++, LV_SYMBOL_DIRECTORY "  %s", "..");

    while(1) {
        res = lv_fs_dir_read(&dir, fn);
        if(res != LV_FS_RES_OK) {   /* read dir error */
            LV_LOG_USER("Driver, file or directory is not exists %d!", res);
            break;
        }

        if(strlen(fn) == 0) {       /*fn is empty, if not more files to read*/
            LV_LOG_USER("Not more files to read!");
            break;
        }

        /* 识别文件类型选择图标 */
        if ((is_end_with(fn, ".png") == true)  || (is_end_with(fn, ".PNG") == true)  ||\
            (is_end_with(fn , ".jpg") == true) || (is_end_with(fn , ".JPG") == true) ||\
            (is_end_with(fn , ".bmp") == true) || (is_end_with(fn , ".BMP") == true) ||\
            (is_end_with(fn , ".gif") == true) || (is_end_with(fn , ".GIF") == true)) {         /* image */
            lv_table_set_cell_value_fmt(explorer->file_table, iRow, iCol, LV_SYMBOL_IMAGE "  %s", fn);
        }
        else if ((is_end_with(fn , ".mp3") == true) || (is_end_with(fn , ".MP3") == true)) {    /* audio */
            lv_table_set_cell_value_fmt(explorer->file_table, iRow, iCol, LV_SYMBOL_AUDIO "  %s", fn);
        }
        else if ((is_end_with(fn , ".mp4") == true) || (is_end_with(fn , ".MP4") == true)) {    /* video */
            lv_table_set_cell_value_fmt(explorer->file_table, iRow, iCol, LV_SYMBOL_VIDEO "  %s", fn);
        }
        else if((is_end_with(fn , ".") == true) || (is_end_with(fn , "..") == true)) {          /*is dir*/
            continue;
        }
        else if(fn[0] == '/') {                                                                 /*is dir*/
            lv_table_set_cell_value_fmt(explorer->file_table, iRow, iCol, LV_SYMBOL_DIRECTORY "  %s", fn+1);
        }
        else {                                                                                  /* file */
            lv_table_set_cell_value_fmt(explorer->file_table, iRow, iCol, LV_SYMBOL_FILE "  %s", fn);
        }

        /* 排列顺序：从左往右，自顶向下 */
        iCol = (iCol + 1)%FILE_TABLE_COLUMN_COUNT;
        if (iCol == 0)
            iRow++;
    }

    lv_fs_dir_close(&dir);
    lv_table_set_row_cnt(explorer->file_table, iRow);
    // lv_100ask_file_explorer_set_sort(obj, FILE_EXPLORER_SORT_KIND); // TODO table-items sorting
    
    lv_obj_scroll_to_y(explorer->file_table, 0, LV_ANIM_OFF);            // 让table移动到最顶部

    /* 显示当前路径标签 */
    lv_memset_00(explorer->cur_path, sizeof(explorer->cur_path));
    strcpy(explorer->cur_path, path);
    lv_label_set_text_fmt(explorer->path_label, LV_SYMBOL_EYE_OPEN" %s", path);

    size_t cur_path_len = strlen(explorer->cur_path);
    if((cur_path_len > 1) && (*((explorer->cur_path) + cur_path_len) != '/') && (cur_path_len < FILE_EXPLORER_PATH_MAX_LEN)) {
        *((explorer->cur_path) + cur_path_len) = '/';
    }  
}


/* 去掉最后的后缀名 */
static void strip_ext(char *dir)
{
    char *end = dir + strlen(dir);

    while (end >= dir && *end != '/') {
        --end;
    }

    if (end > dir) {
        *end = '\0';
    }
    else if (end == dir) {
        *(end+1) = '\0';
    }

}


/* 核验结尾字符串 */
static bool is_end_with(const char * str1, const char * str2)
{
    if(str1 == NULL || str2 == NULL)
        return false;
    
    uint16_t len1 = strlen(str1);
    uint16_t len2 = strlen(str2);
    if((len1 < len2) || (len1 == 0 || len2 == 0))
        return false;
    
    while(len2 >= 1)
    {
        if(str2[len2 - 1] != str1[len1 - 1])
            return false;

        len2--;
        len1--;
    }

    return true;
}

